#include <windows.h>		// for timeGetTime()
#include <mmsystem.h>		// ditto
#include <iostream>			// I/O
#include <GL\freeglut.h>	// GLUT
#include <GL/glu.h>			// for gluPerspective & gluLookAt

#include "main.h"
#include "AreaMap.h"
#include "InputHandler.h"
#include "KMController.h"

#define MAP_SIZE 512
#define SPIDER_RADIUS 20
#define DAMPING 4

bool		first = true;

bool		wireframe=false;

int         windowId;
DWORD		lastTickCount;

AreaMap * map;
KMController * control;

void toggleWireframe()
{
		wireframe=!wireframe;
		
		if(wireframe)
			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
		else 
			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}

void renderScene(){
	// Clear framebuffer & depth buffer
	glClearColor(0.5,0.5,0.5,0.0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// Reset Modelview matrix      	
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glTranslatef(0.0f, 0.0f,-SPIDER_RADIUS);
	control->rotate();

	glColor3f(1.0f, 1.0f, 1.0f);
	glutSolidCube(2); // The Spider

	control->translate();

	glColor3f(1.0f, 1.0f, 1.0f);

	map->render(); // render the heightmap

	// Swap double buffer for flicker-free animation
	glutSwapBuffers();

}

void updateScene(){

	// Wait until at least 16ms passed since start of last frame
	// Effectively caps framerate at ~60fps
	while(timeGetTime()-lastTickCount<16);
	lastTickCount=timeGetTime();

	// Do any other updates here
	control->update();
	
	// Draw the next frame
	glutPostRedisplay();

}

/*void mouseMovement(int x, int y)
{
	if (first){
		first=false;
	}else{

		int diffX=x-lastX; 
		control->applyRotate(diffX/DAMPING,1);   

		int diffY=y-lastY;
		control->applyRotate(diffY/DAMPING,0); 
	}
	lastX=x; 
	lastY=y;
}*/

void setupScene()
{
	std::cout<<"Initializing scene..."<<std::endl;

	//setup the objects
	map = new AreaMap(MAP_SIZE,1);
	control = new KMController(map,60,0,MAP_SIZE,0,MAP_SIZE);
	InputInit(control);

	//Set up Lighting Stuff
	

	glEnable(GL_DEPTH_TEST);

	// Generate GL texture ID & load texture
	
}

void exitScene()
{
	std::cout<<"Exiting scene..."<<std::endl;

	// Close window
	glutDestroyWindow(windowId);

	// Free any allocated memory
	delete map;
	delete control;

	// Exit program
	exit(0);
}

void setViewport(int width, int height) 
{
	// Work out window ratio, avoid divide-by-zero
	if(height==0)
		height=1;
	
	float ratio = float(width)/float(height);

	// Reset projection matrix
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	// Fill screen with viewport
	glViewport(0, 0, width, height);

	// Set a 45 degree perspective
	gluPerspective(45, ratio, .1, 1000);

}

int main(int argc, char *argv[])
{
	// Initialise OpenGL
	glutInit(&argc, argv); 

	// Set window position, size & create window
	glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
	glutInitWindowPosition(50,50);
	glutInitWindowSize(800,600);
	windowId = glutCreateWindow("Example Camera");

	// Set GLUT callback functions
	glutReshapeFunc(setViewport);
	glutDisplayFunc(renderScene);
	glutIdleFunc(updateScene);
	
	// keyboard control functions
	glutKeyboardFunc(KeyDown);
	glutKeyboardUpFunc(KeyUp);
	glutSpecialFunc(KeySpecDown);
	glutSpecialUpFunc(KeySpecUp);
  
	// mouse control functions
	glutMouseFunc(MouseButton);
	glutMotionFunc(MouseAcMove);
	glutPassiveMotionFunc(MousePaMove);
	glutEntryFunc(MouseEntry);

	// Setup OpenGL state & scene resources (models, textures etc)
	setupScene();

	// Show window & start update loop
	glutMainLoop();    

	return 0;
}
